/*
 * 基于muduo网络库实现的TCP翻译客户端
 * 功能：连接翻译服务器，发送待翻译字符串并显示结果
 */

// 包含必要的muduo网络库头文件
#include "include/muduo/net/TcpClient.h"     // TCP客户端核心组件
#include "include/muduo/net/EventLoopThread.h" // 事件循环线程组件
#include "include/muduo/net/TcpConnection.h"   // TCP连接相关组件
#include "include/muduo/base/CountDownLatch.h" // 同步计数器组件
#include <iostream>
#include <functional>  // 用于std::bind绑定回调函数

class TranslateClient {
public:
    /* 构造函数
     * @param sip   服务器IP地址
     * @param sport 服务器端口号
     */
    TranslateClient(const std::string &sip, int sport)
        : _latch(1),  // 初始化计数器（初始值1，用于连接同步）
          // 创建事件循环线程并启动，用于处理网络IO
          _loopthread(),
          // 创建TCP客户端，绑定到事件循环线程的loop，指定服务器地址
          _client(_loopthread.startLoop(), 
                  muduo::net::InetAddress(sip, sport), 
                  "TranslateClient")
    {
        // 设置连接状态变化回调
        _client.setConnectionCallback(
            std::bind(&TranslateClient::onConnection, this, std::placeholders::_1));
        
        // 设置消息接收回调
        _client.setMessageCallback(
            std::bind(&TranslateClient::onMessage, this, std::placeholders::_1,
                     std::placeholders::_2, std::placeholders::_3));
    }

    /* 连接服务器（阻塞式） */
    void connect() {
        _client.connect();  // 发起连接请求
        _latch.wait();     // 阻塞等待直到连接成功建立
    }

    /* 发送翻译请求
     * @param msg 待翻译字符串
     * @return 发送是否成功（取决于连接状态）
     */
    bool send(const std::string &msg) {
        // 检查连接是否有效
        if (_conn && _conn->connected()) {
            _conn->send(msg);  // 通过TCP连接发送数据
            return true;
        }
        return false;
    }   

private:
    /* 连接状态变化回调
     * @param conn TCP连接对象智能指针
     */
    void onConnection(const muduo::net::TcpConnectionPtr& conn) {
        if (conn->connected()) {
            // 连接建立成功时操作
            std::cout << "成功连接到服务器: " 
                      << conn->peerAddress().toIpPort() << std::endl;
            _latch.countDown();  // 计数器减1（解除connect()的阻塞）
            _conn = conn;       // 保存有效连接
        } else {
            // 连接断开时操作
            std::cout << "与服务器断开连接" << std::endl;
            _conn.reset();       // 释放连接对象
        }
    }

    /* 消息接收回调
     * @param conn TCP连接对象
     * @param buf  接收缓冲区
     * @param     时间戳（未使用）
     */
    void onMessage(const muduo::net::TcpConnectionPtr& conn, 
                  muduo::net::Buffer* buf, 
                  muduo::Timestamp) 
    {
        // 从缓冲区提取全部数据并输出翻译结果
        std::cout << "翻译结果：" << buf->retrieveAllAsString() << std::endl;
    }

private:
    muduo::CountDownLatch _latch;          // 同步计数器（用于连接建立等待）
    muduo::net::EventLoopThread _loopthread; // 事件循环线程（单独线程运行loop）
    muduo::net::TcpClient _client;          // TCP客户端对象
    muduo::net::TcpConnectionPtr _conn;     // 当前有效连接指针
};

int main()
{
    // 创建客户端实例（连接本地8888端口）
    TranslateClient client("127.0.0.1", 8888);
    
    // 建立连接（阻塞直到成功）
    client.connect();

    // 交互循环：读取用户输入并发送到服务器
    while(1) 
    {
        std::string buf;
        std::cin >> buf;          // 读取用户输入
        if (!client.send(buf)) {  // 发送并检查结果
            std::cerr << "发送失败：连接已断开" << std::endl;
            break;
        }
    }
    
    return 0;
}